import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import mplfinance as mpf
from datetime import datetime

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

class BYDStockAnalysis:
    def __init__(self, file_path):
        """初始化类，加载数据"""
        self.file_path = file_path
        self.data = None
        self.load_data()
    
    def load_data(self):
        """加载Excel数据"""
        print("正在加载比亚迪股票数据...")
        self.data = pd.read_excel(self.file_path)
        # 打印所有列名
        print("数据列名:", self.data.columns.tolist())
        # 假设数据中包含日期列，将其转换为日期类型
        date_columns = [col for col in self.data.columns if '日期' in col or 'date' in col.lower()]
        if date_columns:
            date_col = date_columns[0]
            print(f"使用 '{date_col}' 作为日期列")
            self.data[date_col] = pd.to_datetime(self.data[date_col])
            self.data = self.data.set_index(date_col)
        print(f"数据加载成功，共 {len(self.data)} 行 {len(self.data.columns)} 列")
    
    def inspect_data(self):
        """观察数据形状，输出前5行，并进行描述性分析"""
        print("\n=== 数据概览 ===")
        print(f"数据形状: {self.data.shape}")
        
        print("\n数据前5行:")
        print(self.data.head())
        
        print("\n=== 描述性统计 ===")
        print(self.data.describe())
    
    def correlation_analysis(self):
        """计算变量之间的相关系数，并绘制相关系数热力图"""
        print("\n=== 相关系数分析 ===")
        # 选择数值型列计算相关系数
        numeric_cols = self.data.select_dtypes(include=[np.number]).columns
        corr_matrix = self.data[numeric_cols].corr()
        
        print("相关系数矩阵:")
        print(corr_matrix)
        
        # 绘制热力图
        plt.figure(figsize=(12, 10))
        sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.2f', square=True)
        plt.title('比亚迪股票数据相关系数热力图')
        plt.tight_layout()
        plt.savefig('correlation_heatmap.png', dpi=300)
        print("\n相关系数热力图已保存为 'correlation_heatmap.png'")
    
    def plot_2023_close_price(self):
        """绘制2023年全年的收盘价时序图"""
        print("\n=== 2023年收盘价时序图分析 ===")
        # 筛选2023年的数据
        df_2023 = self.data[self.data.index.year == 2023]
        
        if df_2023.empty:
            print("警告: 未找到2023年的数据")
            return
        
        plt.figure(figsize=(14, 7))
        plt.plot(df_2023.index, df_2023['收盘'], 'b-', linewidth=2)
        plt.title('比亚迪2023年收盘价时序图')
        plt.xlabel('日期')
        plt.ylabel('收盘价')
        plt.grid(True, linestyle='--', alpha=0.7)
        plt.tight_layout()
        plt.savefig('2023_close_price.png', dpi=300)
        print("\n2023年收盘价时序图已保存为 '2023_close_price.png'")
    
    def plot_k_line_chart(self):
        """绘制2023年4月到2023年6月的K线图"""
        print("\n=== 2023年4-6月K线图分析 ===")
        # 筛选2023年4月到6月的数据
        start_date = pd.Timestamp('2023-04-01')
        end_date = pd.Timestamp('2023-06-30')
        df_k_line = self.data[(self.data.index >= start_date) & (self.data.index <= end_date)]
        
        if df_k_line.empty:
            print("警告: 未找到2023年4-6月的数据")
            return
        
        # 确保数据中包含所需的列
        if ('开盘' in df_k_line.columns and '最高' in df_k_line.columns and 
            '最低' in df_k_line.columns and '收盘' in df_k_line.columns):
            # 准备K线图数据 - mplfinance需要特定的列名
            k_data = df_k_line.copy()
            # 重命名列为mplfinance所需的英文列名
            k_data = k_data.rename(columns={
                '开盘': 'Open',
                '最高': 'High', 
                '最低': 'Low',
                '收盘': 'Close',
                '成交量': 'Volume'
            })
            
            # 设置K线图样式
            mc = mpf.make_marketcolors(up='red', down='green', inherit=True)
            s = mpf.make_mpf_style(marketcolors=mc, gridaxis='both', gridstyle='--', y_on_right=False)
            
            # 绘制K线图
            mpf.plot(k_data, 
                     type='candle', 
                     style=s, 
                     title='比亚迪2023年4-6月K线图', 
                     ylabel='价格', 
                     volume=True, 
                     ylabel_lower='成交量', 
                     savefig='k_line_chart.png')
            print("\n2023年4-6月K线图已保存为 'k_line_chart.png'")
            
            # K线图分析
            self.analyze_k_line(df_k_line)
        else:
            print("错误: 数据中缺少K线图所需的列（开盘价、最高价、最低价、收盘价）")
    
    def analyze_k_line(self, df):
        """对K线图进行简单分析"""
        print("\n=== K线图分析结果 ===")
        
        # 计算基本统计量
        start_price = df['收盘'].iloc[0]
        end_price = df['收盘'].iloc[-1]
        max_price = df['最高'].max()
        min_price = df['最低'].min()
        
        # 计算涨跌幅
        price_change = end_price - start_price
        percent_change = (price_change / start_price) * 100
        
        print(f"起始价格: {start_price:.2f}")
        print(f"结束价格: {end_price:.2f}")
        print(f"最高价: {max_price:.2f}")
        print(f"最低价: {min_price:.2f}")
        print(f"价格变动: {price_change:.2f} ({percent_change:.2f}%)")
        
        # 分析趋势
        if percent_change > 5:
            print("总体趋势: 上涨趋势明显")
        elif percent_change < -5:
            print("总体趋势: 下跌趋势明显")
        else:
            print("总体趋势: 震荡行情")
    
    def run_all_analysis(self):
        """运行所有分析任务"""
        self.inspect_data()
        self.correlation_analysis()
        self.plot_2023_close_price()
        self.plot_k_line_chart()
        print("\n所有分析任务已完成！")

if __name__ == "__main__":
    # 文件路径
    file_path = "../chapter4/比亚迪后复权历史行情数据.xlsx"
    
    # 创建分析实例并运行所有分析
    analysis = BYDStockAnalysis(file_path)
    analysis.run_all_analysis()